package com.ev.aslReport.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;;
import com.ev.asl.config.KisApiUrlParam;
import com.ev.aslReport.service.ReportProcessingDataService;
import com.ev.aslReport.service.ReportService;
import com.ev.aslReport.vo.*;
import com.ev.framework.utils.HttpClientUtils;
import com.ev.framework.utils.R;
import com.ev.framework.utils.StringUtils;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: π
 * @date 2022/7/22 16:17
 * @described:
 */
@Slf4j
@Service
public class ReportServiceImpl implements ReportService {

    @Resource
    private KisApiUrlParam kisApiUrlParam;
    @Resource
    private    ReportProcessingDataService  reportProcessingDataService;


    @Override
    public R getRemoteDataOfBefore(int sign, String materielName,String materialNumber ,String datestar, String dateend, String stockName, int pageSize, int pageNo,String year,String materialModel) {
        ReportParamVo reportParamVo = new ReportParamVo();
        reportParamVo.setAcct("xrtest");
        reportParamVo.setDatestar(datestar);
        reportParamVo.setDateend(dateend);
        reportParamVo.setPageNo(pageNo);
        reportParamVo.setPageSize(pageSize);
        switch (sign) {
            case 1:
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_one(),materialModel);
            case 2:
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_two(),materialModel);
            case 3:
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_three(),materialModel);
            case 4:
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_four(),materialModel);
            case 5:
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_five(),materialModel);
            case 6:
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_six(),materialModel);
            case 7:
                reportParamVo.setMaterialNumber(StringUtils.isNotBlank(materialNumber)?materialNumber:null);
                reportParamVo.setStockName(StringUtils.isNotBlank(stockName)?stockName:null);
                reportParamVo.setMaterialName(StringUtils.isNotBlank(materielName)?materielName:null);
                log.error("reportParamVo"+reportParamVo);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_seven(),materialModel);
            case 8:
                reportParamVo.setYear(year);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_eight(),materialModel);
            case 9:
                reportParamVo.setYear(year);
                return this.getRemoteDataUnderway(sign,reportParamVo, kisApiUrlParam.getUrl_report_nine(),materialModel);
            default:
                return R.error();
        }
    }

    public Triple<Boolean, Integer, JSONArray> getRemoteData(ReportParamVo reportParamVo, String url) {
        log.info("-------url:"+url);
        log.info("-------参数:"+JSONObject.toJSONString(reportParamVo));
        String datas = HttpClientUtils.sendJsonStr(url, JSONObject.toJSONString(reportParamVo));
//        log.info("-----datas:"+datas);
        if (StringUtils.isNotBlank(datas)) {
            Object parse = JSON.parse(datas);
            RemoteDataVo remoteDataVo = JSON.parseObject(parse.toString(), RemoteDataVo.class);
            if (Objects.equals("0", remoteDataVo.getStatus()) && Objects.equals("ok", remoteDataVo.getMsg())) {
                String result = remoteDataVo.getDatas();
                if (StringUtils.isNotBlank(result)) {
//                    JSONObject value = JSONObject.parseObject(result);
                    JSONArray value = JSONObject.parseArray(result);
                    return Triple.of(true, remoteDataVo.getRecords(), value);
                }
            }
        }
        return Triple.of(false, null, null);
    }

    public R getRemoteDataUnderway(int sign, ReportParamVo reportParamVo, String url,String materialModel) {
        //远程获取
        Map<String, Object> dataMap = Maps.newHashMapWithExpectedSize(2);
//        dataMap.put("data",null);
        Triple<Boolean, Integer, JSONArray> remoteDataUnderway = this.getRemoteData(reportParamVo, url);
//        JSONArray right = remoteDataUnderway.getRight();
//        JSONArray jsonArray = new JSONArray();
//        right.stream().filter(r-> (ObjectUtil.isEmpty(JSONObject.parseObject(r.toString()).get("规格型号"))? "" : JSONObject.parseObject(r.toString()).get("规格型号")).toString().contains(ObjectUtil.isEmpty(materialModel)? "" : materialModel) ).forEach(r-> jsonArray.add(r));
//        remoteDataUnderway.of(remoteDataUnderway.getLeft(),remoteDataUnderway.getMiddle(),jsonArray);
        log.info("----one  remoteDataUnderway：{}",remoteDataUnderway);

        if (remoteDataUnderway.getLeft()) {
            //转换
            reportParamVo.setPageSize(remoteDataUnderway.getMiddle());
            Triple<Boolean, Integer, JSONArray> integerJSONObjectPair = this.dealDataConversion(sign, remoteDataUnderway, reportParamVo, url,materialModel);
            if(integerJSONObjectPair.getLeft()){
                switch (sign){
                    case 1 :
                        BigDecimal totalInCount = BigDecimal.ZERO;
                        BigDecimal totalOutCount = BigDecimal.ZERO;
                        BigDecimal totalBalanceCount = BigDecimal.ZERO;
                        List<reportOneVO> reportOneVoS = JSON.parseArray(JSON.toJSONString(integerJSONObjectPair.getRight()), reportOneVO.class);
                        for (reportOneVO reportOneVo : reportOneVoS) {
                            BigDecimal inCount = reportOneVo.getInCount();
                            BigDecimal outCount = reportOneVo.getOutCount();
                            BigDecimal balanceCount = reportOneVo.getBalanceCount();
                            totalInCount = (ObjectUtils.isEmpty(totalInCount) ? BigDecimal.ONE : totalInCount)
                                    .add(ObjectUtils.isEmpty(inCount) ? BigDecimal.ONE : inCount);
                            totalOutCount = (ObjectUtils.isEmpty(totalOutCount) ? BigDecimal.ONE : totalOutCount)
                                    .add(ObjectUtils.isEmpty(outCount) ? BigDecimal.ONE : outCount);
                            totalBalanceCount = (ObjectUtils.isEmpty(totalBalanceCount) ? BigDecimal.ONE : totalBalanceCount)
                                    .add(ObjectUtils.isEmpty(balanceCount) ? BigDecimal.ONE : balanceCount);
                        }
                        dataMap.put("totalBalanceCount",totalBalanceCount);
                        dataMap.put("totalInCount",totalInCount);
                        dataMap.put("totalOutCount",totalOutCount);
                        break;
                    case 2 :
                        BigDecimal totalStorageQty = BigDecimal.ZERO;
                        List<ReportTwoVo> reportTwoVos = JSON.parseArray(JSON.toJSONString(integerJSONObjectPair.getRight()), ReportTwoVo.class);
                        for (ReportTwoVo reportTwoVo : reportTwoVos) {
                            BigDecimal storageQty = reportTwoVo.getStorageQty();
                            totalStorageQty = (ObjectUtils.isEmpty(totalStorageQty) ? BigDecimal.ONE : totalStorageQty)
                                    .add(ObjectUtils.isEmpty(storageQty) ? BigDecimal.ONE : storageQty);
                        }
                        dataMap.put("totalStorageQty",totalStorageQty);
                        break;
                    case 3 :
                        BigDecimal outStockQtySum = BigDecimal.ZERO;
                        List<ReportThreeVo> ReportThreeVos = JSON.parseArray(JSON.toJSONString(integerJSONObjectPair.getRight()), ReportThreeVo.class);
                        for (ReportThreeVo reportThreeVo : ReportThreeVos) {
                            BigDecimal outStockQty = reportThreeVo.getOutStockQty();
                            outStockQtySum = (ObjectUtils.isEmpty(outStockQtySum) ? BigDecimal.ONE : outStockQtySum)
                                    .add(ObjectUtils.isEmpty(outStockQty) ? BigDecimal.ONE : outStockQty);
                        }
                        dataMap.put("outStockQtySum",outStockQtySum);
                        break;
                    case 4 :
                        BigDecimal totalSafetyStock = BigDecimal.ZERO;
                        BigDecimal totalActualInventory = BigDecimal.ZERO;
                        List<ReportFourVo> reportFourVos = JSON.parseArray(JSON.toJSONString(integerJSONObjectPair.getRight()), ReportFourVo.class);
                        for (ReportFourVo reportFourVo : reportFourVos) {
                            BigDecimal safetyStock = reportFourVo.getSafetyStock();
                            BigDecimal actualInventory = reportFourVo.getActualInventory();
                            totalSafetyStock = (ObjectUtils.isEmpty(totalSafetyStock) ? BigDecimal.ONE : totalSafetyStock)
                                    .add(ObjectUtils.isEmpty(safetyStock) ? BigDecimal.ONE : safetyStock);
                            totalActualInventory = (ObjectUtils.isEmpty(totalActualInventory) ? BigDecimal.ONE : totalActualInventory)
                                    .add(ObjectUtils.isEmpty(actualInventory) ? BigDecimal.ONE : actualInventory);
                        }
                        dataMap.put("totalSafetyStock",totalSafetyStock);
                        dataMap.put("totalActualInventory",totalActualInventory);
                        break;
                    case 5:
                        BigDecimal totalStock = BigDecimal.ZERO;
                        BigDecimal totalAvailableStock = BigDecimal.ZERO;
                        BigDecimal totalLockLibraryAmount = BigDecimal.ZERO;
                        BigDecimal totalScheduledReceipt = BigDecimal.ZERO;
                        BigDecimal totalAllocation = BigDecimal.ZERO;
                        List<ReportFiveVo> reportFiveVos = JSON.parseArray(JSON.toJSONString(integerJSONObjectPair.getRight()), ReportFiveVo.class);
                        for (ReportFiveVo reportFiveVo : reportFiveVos) {
                            BigDecimal stock = reportFiveVo.getStock();
                            BigDecimal availableStock = reportFiveVo.getAvailableStock();
                            BigDecimal lockLibraryAmount = reportFiveVo.getLockLibraryAmount();
                            BigDecimal scheduledReceipt = reportFiveVo.getScheduledReceipt();
                            BigDecimal allocation = reportFiveVo.getAllocation();

                            totalStock = (ObjectUtils.isEmpty(totalStock) ? BigDecimal.ONE : totalStock)
                                    .add(ObjectUtils.isEmpty(stock) ? BigDecimal.ONE : stock);

                            totalAvailableStock = (ObjectUtils.isEmpty(totalAvailableStock) ? BigDecimal.ONE : totalAvailableStock)
                                    .add(ObjectUtils.isEmpty(availableStock) ? BigDecimal.ONE : availableStock);

                            totalLockLibraryAmount = (ObjectUtils.isEmpty(totalLockLibraryAmount) ? BigDecimal.ONE : totalLockLibraryAmount)
                                    .add(ObjectUtils.isEmpty(lockLibraryAmount) ? BigDecimal.ONE : lockLibraryAmount);

                            totalScheduledReceipt = (ObjectUtils.isEmpty(totalScheduledReceipt) ? BigDecimal.ONE : totalScheduledReceipt)
                                    .add(ObjectUtils.isEmpty(scheduledReceipt) ? BigDecimal.ONE : scheduledReceipt);

                            totalAllocation = (ObjectUtils.isEmpty(totalAllocation) ? BigDecimal.ONE : totalAllocation)
                                    .add(ObjectUtils.isEmpty(allocation) ? BigDecimal.ONE : allocation);
                        }
                        dataMap.put("totalStock",totalStock);
                        dataMap.put("totalAvailableStock",totalAvailableStock);
                        dataMap.put("totalLockLibraryAmount",totalLockLibraryAmount);
                        dataMap.put("totalScheduledReceipt",totalScheduledReceipt);
                        dataMap.put("totalAllocation",totalAllocation);
                        break;
                }
                dataMap.put("data",integerJSONObjectPair.getRight());
                dataMap.put("pageNo",reportParamVo.getPageNo());
                dataMap.put("pageSize",reportParamVo.getPageSize());
                dataMap.put("total",integerJSONObjectPair.getMiddle());
                dataMap.put("totalPage",(integerJSONObjectPair.getMiddle() + reportParamVo.getPageSize() - 1) / reportParamVo.getPageSize());

            }
        }
        return R.ok(dataMap);
    }

//    /**
//     * 增加几个字段
//     * @param sign
//     * @param reportParamVo
//     * @param url
//     * @return
//     */
//    public R getRemoteDataUnderway2(int sign, ReportParamVo reportParamVo, String url) {
//        //远程获取
//        Map<String, Object> dataMap = Maps.newHashMapWithExpectedSize(2);
//        Triple<Boolean, Integer, JSONArray> remoteDataResult = this.getRemoteData2(reportParamVo, url);
//
//
//
//        reportParamVo.setPageSize(null);
//        Triple<Boolean, Integer, JSONArray> remoteDataAll = this.getRemoteData2(reportParamVo, url);
//        if (remoteDataAll.getLeft()) {
//            //转换
//            Triple<Boolean, Integer, JSONArray> integerJSONObjectPair = this.dealDataConversion(sign, remoteDataAll);
//            if(integerJSONObjectPair.getLeft()){
//                dataMap.put("data",integerJSONObjectPair.getRight());
//                dataMap.put("pageNo",reportParamVo.getPageNo());
//                dataMap.put("pageSize",reportParamVo.getPageSize());
//                dataMap.put("total",integerJSONObjectPair.getMiddle());
//                dataMap.put("totalPage",(integerJSONObjectPair.getMiddle() + reportParamVo.getPageSize() - 1) / reportParamVo.getPageSize());
//            }
//        }
//
//
//
//        if (remoteDataResult.getLeft()) {
//            return R.ok(dataMap);
//        }
//        JSONArray data = remoteDataResult.getRight();
//        reportParamVo.setPageSize(remoteDataResult.getMiddle());
//        Triple<Boolean, Integer, JSONArray> remoteDataUnderway2 = this.getRemoteData2(reportParamVo, url);
//        //转换
//        Triple<Boolean, Integer, JSONArray> integerJSONObjectPair = this.dealDataConversion(sign, remoteDataResult);
//        if(integerJSONObjectPair.getLeft()){
//            dataMap.put("data",integerJSONObjectPair.getRight());
//            dataMap.put("pageNo",reportParamVo.getPageNo());
//            dataMap.put("pageSize",reportParamVo.getPageSize());
//            dataMap.put("total",integerJSONObjectPair.getMiddle());
//            dataMap.put("totalPage",(integerJSONObjectPair.getMiddle() + reportParamVo.getPageSize() - 1) / reportParamVo.getPageSize());
//        }
//        return R.ok(dataMap);
//    }

    /**
     *
     * @param reportParamVo
     * @param url
     * @return Triple.of(调用是否成功, 记录总数, 查询数据)
     */
    public Triple<Boolean, Integer, JSONArray> getRemoteData2(ReportParamVo reportParamVo, String url) {
        log.info("-------url:"+url);
        log.info("-------参数:"+JSONObject.toJSONString(reportParamVo));
        String datas = HttpClientUtils.sendJsonStr(url, JSONObject.toJSONString(reportParamVo));
        if (StringUtils.isNotBlank(datas)) {
            Object parse = JSON.parse(datas);
            RemoteDataVo remoteDataVo = JSON.parseObject(parse.toString(), RemoteDataVo.class);
            if (Objects.equals("0", remoteDataVo.getStatus()) && Objects.equals("ok", remoteDataVo.getMsg())) {
                String result = remoteDataVo.getDatas();
                if (StringUtils.isNotBlank(result)) {
//                    JSONObject value = JSONObject.parseObject(result);
                    JSONArray value = JSONObject.parseArray(result);
                    return Triple.of(true, remoteDataVo.getRecords(), value);
                }
            }
        }
        return Triple.of(false, null, null);
    }

    public Triple<Boolean, Integer, JSONArray> dealDataConversion(int sign, Triple<Boolean, Integer, JSONArray> remoteDataUnderway, ReportParamVo reportParamVo, String url,String materialModel) {
        Triple<Boolean, Integer, JSONArray> remoteDataAll = new Triple<Boolean, Integer, JSONArray>() {
            @Override
            public Boolean getLeft() {
                return null;
            }

            @Override
            public Integer getMiddle() {
                return null;
            }

            @Override
            public JSONArray getRight() {
                return null;
            }
        };
        switch (sign) {
            case 1:
                //目的是为了获取某些字段的合计值
                remoteDataAll = this.getRemoteData(reportParamVo, url);
                Map<String, BigDecimal> balanceCountMap = new HashMap<>();
                Map<String, BigDecimal> inCountMap = new HashMap<>();
                Map<String, BigDecimal> outCountMap = new HashMap<>();
                if (remoteDataAll.getLeft()) {
                    List<reportOneVO> reportOneVOS = reportProcessingDataService.processingDataOfOne2(remoteDataAll,materialModel,reportParamVo.getMaterialNumber());
                    balanceCountMap = reportOneVOS.stream().collect(Collectors.toMap(reportOneVO::getMaterieCode, reportOneVO::getBalanceCount, BigDecimal::add));
                    outCountMap = reportOneVOS.stream().collect(Collectors.toMap(reportOneVO::getMaterieCode, reportOneVO::getOutCount, BigDecimal::add));
                    inCountMap = reportOneVOS.stream().collect(Collectors.toMap(reportOneVO::getMaterieCode, reportOneVO::getInCount, BigDecimal::add));
                }

                log.info("----one  remoteDataAll：{}",remoteDataAll);
                return reportProcessingDataService.processingDataOfOne(remoteDataUnderway, balanceCountMap, inCountMap, outCountMap,materialModel,reportParamVo.getMaterialNumber());
            case 2:
                //目的是为了获取某些字段的合计值
                remoteDataAll = this.getRemoteData(reportParamVo, url);
                Map<String, BigDecimal> storageQtySMap = new HashMap<>();
                if (remoteDataAll.getLeft()) {
                    List<ReportTwoVo> reportTwoVOS = reportProcessingDataService.processingDataOfTwo2(remoteDataAll,materialModel,reportParamVo.getMaterialName());
                    storageQtySMap = reportTwoVOS.stream().collect(Collectors.toMap(ReportTwoVo::getMaterieCode, ReportTwoVo::getStorageQty, BigDecimal::add));
                }

                log.info("----Two  remoteDataAll：{}",remoteDataAll);
                return reportProcessingDataService.processingDataOfTwo(remoteDataUnderway, storageQtySMap,materialModel,reportParamVo.getMaterialName());
            case 3:
                //目的是为了获取某些字段的合计值
                remoteDataAll = this.getRemoteData(reportParamVo, url);
                Map<String, BigDecimal> outStockQtySMap = new HashMap<>();
                if (remoteDataAll.getLeft()) {
                    List<ReportThreeVo> reportThreeVOS = reportProcessingDataService.processingDataOfThree2(remoteDataAll,materialModel,reportParamVo.getMaterialName());
                    outStockQtySMap = reportThreeVOS.stream().collect(Collectors.toMap(ReportThreeVo::getMaterieCode, ReportThreeVo::getOutStockQty, BigDecimal::add));
                }
                return reportProcessingDataService.processingDataOfThree(remoteDataUnderway, outStockQtySMap,materialModel,reportParamVo.getMaterialName());
            case 4:
                return reportProcessingDataService.processingDataOfFour(remoteDataUnderway,materialModel,reportParamVo.getMaterialName());
            case 5:
                return reportProcessingDataService.processingDataOfFive(remoteDataUnderway,materialModel,reportParamVo.getMaterialName());
            case 6:
                return reportProcessingDataService.processingDataOfSix(remoteDataUnderway,materialModel,reportParamVo.getMaterialName());
            case 7:
                return reportProcessingDataService.processingDataOfSeven(remoteDataUnderway,materialModel,reportParamVo.getMaterialName());
            case 8:
                return reportProcessingDataService.processingDataOfEight(remoteDataUnderway);
            case 9:
                return reportProcessingDataService.processingDataOfNine(remoteDataUnderway);
            default:
                break;
        }
        return Triple.of(false, 1, null);
    }






}
